package com.suning.sawp.service.impl.dao;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.mapreduce.MapReduceResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import com.suning.framework.dal.client.DalClient;
import com.suning.sawp.dto.precharge.ChargeOrderForPageRtn;
import com.suning.sawp.dto.precharge.PrechargeStatis;
import com.suning.sawp.dto.precharge.StatisChargeOrderForPageRtn;
import com.suning.sawp.dto.precharge.ChargeOrderRtn.OrderStatus;
import com.suning.sawp.intf.dao.PreChargeDaoService;
import com.suning.sawp.po.precharge.PreChargeOrder;
import com.suning.sawp.po.precharge.PrechargeActivity;
import com.suning.sawp.po.precharge.PrechargeRule;
import com.suning.sawp.service.util.BeanUtil;

/**
 * 
 * 现金充值记录列表数据库操作<br> 
 * 〈功能详细描述〉
 *
 * @author 14062606
 * @see [相关类/方法]（可选）
 * @since [产品/模块版本] （可选）
 */
@Service
public class PreChargeDaoServiceImpl implements PreChargeDaoService{

	@Resource
    MongoOperations mongoTemplate;
	
	@Resource
	DalClient dalClient;
	
    private static final Integer SORT_COLUMN_CHARGE_TIMES = 0;
    
    private static final Integer SORT_COLUMN_COUPON_AMOUNT = 1;
    
    private static final Integer SORT_TYPE_ASC = 0;
    
    private static final Integer SORT_TYPE_DESC = 1;
	
	@Override
	public PreChargeOrder queryOrderBySerialNo(String clientSerialNo) {
		Query query = new Query();
        Criteria criteria = new Criteria();
        criteria.and("clientSerialNo").is(clientSerialNo);
        query.addCriteria(criteria);
		return mongoTemplate.findOne(query, PreChargeOrder.class);
	}

	@Override
	public int countChargeOrderForPage(Date startTime, Date endTime,
			String regionCode, String storeCode) {
		// 初始化db查询参数
        Query query = new Query();
        Criteria criteria = new Criteria();
      
        criteria.and(PreChargeOrder.Attributes.PAY_TIME)
    		.gte(startTime).lte(endTime).and(PreChargeOrder.Attributes.STORE_CODE).exists(true);
        
        if (StringUtils.isNotBlank(regionCode)){
            criteria.and(PreChargeOrder.Attributes.REGION_CODE).is(regionCode);
        }
        if (StringUtils.isNotBlank(storeCode)){
        	criteria.and(PreChargeOrder.Attributes.STORE_CODE).is(storeCode);
        }
        query.addCriteria(criteria);
        
        return (int) mongoTemplate.count(query, PreChargeOrder.class);
	}

	@Override
	public List<ChargeOrderForPageRtn> queryChargeOrderForPage(Date startTime,
			Date endTime, String regionCode, String storeCode, Integer chargeAmount,
            Integer couponAmount, Integer startIndex,
			Integer limit) {
		List<ChargeOrderForPageRtn> list = new ArrayList<ChargeOrderForPageRtn>();
		Query query = new Query();
        Criteria criteria = new Criteria();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(endTime);
        calendar.add(Calendar.DATE, 1);
        criteria.and(PreChargeOrder.Attributes.PAY_TIME)
        	.gte(startTime).lte(calendar.getTime()).and(PreChargeOrder.Attributes.STATUS).is(OrderStatus.DONE_SEND_COUPON);
        if (null != chargeAmount && null != couponAmount) {
            criteria.and(PreChargeOrder.Attributes.CHARGE_AMOUNT).is(String.valueOf(chargeAmount))
            .and(PreChargeOrder.Attributes.COUPON_AMOUNT).is(couponAmount);
        }
        	
        if (StringUtils.isNotBlank(regionCode)){
            criteria.and(PreChargeOrder.Attributes.REGION_CODE).is(regionCode);
        }
        if (StringUtils.isNotBlank(storeCode)){
        	criteria.and(PreChargeOrder.Attributes.STORE_CODE).is(storeCode);
        }
        query.addCriteria(criteria);
        
        String mapFunc = "function(){emit(this.storeCode+this.ruleCode+this.chargeAmount, {chargeAmount:this.chargeAmount,couponAmount:this.couponAmount,regionName:this.regionName,storeName:this.storeName,couponCount:1});}";
        String reduceFunc = "function (key, value) {var result = {chargeAmount:'',couponAmount:'',activityName:'',regionName:'',storeName:'',couponCount:0};"+
        "for  ( var i=0;i<value.length;i++) {"+
        "result.chargeAmount= value[i].chargeAmount;result.couponAmount= value[i].couponAmount;" +
        "result.regionName= value[i].regionName;"+
        "result.storeName= value[i].storeName;"+
        "result.couponCount += value[i].couponCount;"+
        "}"+
        "return result;}";
        
        MapReduceResults<StatisChargeOrderForPageRtn> mapReduce = mongoTemplate.mapReduce(query,"PrechargeOrder",mapFunc,reduceFunc,StatisChargeOrderForPageRtn.class);
        if(mapReduce != null){
            for(StatisChargeOrderForPageRtn coupon : mapReduce){
               list.add(coupon.getValue());
            }
        }
        
        return list;
	}

    @Override
    public List<ChargeOrderForPageRtn> queryChargeOrderForPage(Date startTime, Date endTime, String regionCode,
            String storeCode, Integer startIndex, Integer limit) {
        return queryChargeOrderForPage(startTime, endTime, regionCode, storeCode, null, null, startIndex, limit);
    }

    @Override
    public int insertPrechargeAct(PrechargeActivity act) {
        return dalClient.persist(act).intValue();
    }

    @Override
    public void insertRule(PrechargeRule rule) {
        dalClient.persist(rule);
    }

    @Override
    public void updateActStatus(String storeCode, Integer status,Integer operateType) {
        Map<String,Object> paramMap = new HashMap<String,Object>();
        paramMap.put("unequalStatus", PrechargeActivity.promoStatusType.END);
        paramMap.put("unequalType", PrechargeActivity.OperateType.POS);
        paramMap.put("unequalType1", PrechargeActivity.OperateType.ADMIN_OFFSALE);
        paramMap.put("promoStatus", status);
        paramMap.put("storeCode", storeCode);
        paramMap.put("promoOperateType", operateType);
        dalClient.execute("PRE_CHARGE_ACT.UPDATE_STATUS_BY_STORE", paramMap);
    }

    @Override
    public List<PrechargeActivity> queryAct(PrechargeActivity queryCon) {
        Map<String,Object> paramMap = BeanUtil.describe(queryCon);
        return dalClient.queryForList("PRE_CHARGE_ACT.QUERY_ACT_BY_CON", paramMap,PrechargeActivity.class);
    }

    @Override
    public List<PrechargeRule> queryActRule(Integer promotionId) {
        Map<String,Object> paramMap = new HashMap<String,Object>();
        paramMap.put("promotionId", promotionId);
        return dalClient.queryForList("PRE_CHARGE_ACT.QUERY_RULE_BY_CON", paramMap,PrechargeRule.class);
    }

    @Override
    public void updateActStatusByEndTime(Integer endTime) {
        Map<String,Object> paramMap = new HashMap<String,Object>();
        paramMap.put("promoStatus", PrechargeActivity.promoStatusType.END);
        paramMap.put("promoEndTime", endTime);
        paramMap.put("promoOperateType", PrechargeActivity.OperateType.JOB);
        dalClient.execute("PRE_CHARGE_ACT.UPDATE_STATUS_BY_ENDTIME", paramMap);
    }

    @Override
    public void updateActStatusByRuleCode(String ruleCode) {
        Map<String,Object> paramMap = new HashMap<String,Object>();
        paramMap.put("promoStatus", PrechargeActivity.promoStatusType.OFFSALE);
        paramMap.put("unequalStatus", PrechargeActivity.promoStatusType.END);
        paramMap.put("ruleCode", ruleCode);
        paramMap.put("promoOperateType", PrechargeActivity.OperateType.POS);
        dalClient.execute("PRE_CHARGE_ACT.UPDATE_STATUS_BY_RULECODE", paramMap);
    }

    @Override
    public PrechargeActivity queryOnSaleActivity(String storeCode) {
        Map<String,Object> paramMap = new HashMap<String,Object>();
        paramMap.put("promoStatus", PrechargeActivity.promoStatusType.ONSALE);
        paramMap.put("storeCode", storeCode);
        return dalClient.queryForObject("PRE_CHARGE_ACT.QUERY_ACT_BY_CON", paramMap,PrechargeActivity.class);
    }

    @Override
    public List<PrechargeStatis> queryPrechargeStatis(String storeCode,Integer pageNo,Integer pageSize, Integer sortColumn,
            Integer sortType) {
        Map<String,Object> paramMap = new HashMap<String,Object>();
        paramMap.put("storeCode", storeCode);
        paramMap.put("startIndex", pageSize*(pageNo-1));
        paramMap.put("maxCount", pageSize);
        if(sortColumn != null  && sortType != null){
            if(sortColumn == SORT_COLUMN_CHARGE_TIMES){
                paramMap.put("sortColumn", "CHARGE_COUNT");
            }else if(sortColumn == SORT_COLUMN_COUPON_AMOUNT){
                paramMap.put("sortColumn", "COUPON_AMOUNT");
            }
            if(sortType == SORT_TYPE_ASC){
                paramMap.put("sortType", "ASC");
            }else if(sortType == SORT_TYPE_DESC){
                paramMap.put("sortType", "DESC");
            }
        }else{
            paramMap.put("sortColumn", "CHARGE_COUNT");
            paramMap.put("sortType", "DESC");
        }
        return dalClient.queryForList("PRE_CHARGE_ACT.SELECT_STORE_STATIS", paramMap,PrechargeStatis.class);
    }

    @Override
    public int queryPrechargeStatisCount(String storeCode) {
        Map<String,Object> paramMap = new HashMap<String,Object>();
        paramMap.put("storeCode", storeCode);
        Map<String, Object> numMap = dalClient.queryForMap("PRE_CHARGE_ACT.SELECT_STATIS_COUNT", paramMap);
        return numMap == null ? 0 : ((Number)numMap.get("NUM")).intValue();
    }

    @Override
    public List<PrechargeActivity> queryActListPage(String keyWord, String startTime,
            String endTime, Integer pageNo, Integer pageSize) {
        Map<String,Object> paramMap = new HashMap<String,Object>();
        if(StringUtils.isNotBlank(keyWord) && keyWord.length() == 4){
            paramMap.put("storeCode", keyWord);
        }else if(StringUtils.isNotBlank(keyWord)){
            paramMap.put("ruleCode", keyWord);
        }
        if(StringUtils.isNotBlank(startTime)){
            paramMap.put("promoStartTime", startTime.replace("-", ""));
        }
        if(StringUtils.isNotBlank(endTime)){
            paramMap.put("promoEndTime", endTime.replace("-", ""));
        }
        paramMap.put("start", pageSize*(pageNo-1));
        paramMap.put("limit", pageSize);
        return dalClient.queryForList("PRE_CHARGE_ACT.QUERY_PROMO_PAGE", paramMap,PrechargeActivity.class);
    }

    @Override
    public int queryActListPageCount(String keyWord, String startTime, String endTime) {
        Map<String,Object> paramMap = new HashMap<String,Object>();
        if(StringUtils.isNotBlank(keyWord) && keyWord.length() == 4){
            paramMap.put("storeCode", keyWord);
        }else if(StringUtils.isNotBlank(keyWord)){
            paramMap.put("ruleCode", keyWord);
        }
        if(StringUtils.isNotBlank(startTime)){
            paramMap.put("promoStartTime", startTime.replace("-", ""));
        }
        if(StringUtils.isNotBlank(endTime)){
            paramMap.put("promoEndTime", endTime.replace("-", ""));
        }
        Map<String, Object> numMap = dalClient.queryForMap("PRE_CHARGE_ACT.QUERY_PROMO_PAGE_COUNT", paramMap);
        return numMap == null ? 0 : ((Number)numMap.get("NUM")).intValue();
    }

    @Override
    public void updateStatusByPromoId(Integer promotionId, Integer status) {
        Map<String,Object> paramMap = new HashMap<String,Object>();
        paramMap.put("promotionId", promotionId);
        paramMap.put("promoStatus", status);
        if(status == PrechargeActivity.promoStatusType.ONSALE){
            paramMap.put("promoOperateType", PrechargeActivity.OperateType.ADMIN_ONSALE);
        }else if(status == PrechargeActivity.promoStatusType.OFFSALE){
            paramMap.put("promoOperateType", PrechargeActivity.OperateType.ADMIN_OFFSALE);
        }
        dalClient.execute("PRE_CHARGE_ACT.UPDATE_STATUS_BY_ID", paramMap);
    }
    
}
